package com.learn.redis.lock.impl;

import com.learn.redis.lock.CusLockInfo;
import com.learn.redis.lock.LockService;
import com.learn.redis.lock.LockType;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author PC
 * 写锁实现
 */
@Component
public class WriteLockServiceImpl implements LockService {
    private final static Logger LOGGER = LoggerFactory.getLogger(WriteLockServiceImpl.class);

    private RedissonClient redissonClient;

    @Autowired
    public void setRedissonClient(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    @Override
    public Boolean lock() {
        CusLockInfo cusLockInfo = getLockInfoThreadLocal();
        return this.lock(cusLockInfo);
    }

    @Override
    public Boolean lock(CusLockInfo cusLockInfo) {
        RLock writeLock = redissonClient.getReadWriteLock(cusLockInfo.getLockKey()).writeLock();
        try {
            return writeLock.tryLock(cusLockInfo.getWaitTime(), cusLockInfo.getLeaseTime(), cusLockInfo.getTimeUnit());
        } catch (InterruptedException interruptedException) {
            LOGGER.error("get lock failed, error:{}", ExceptionUtils.getStackTrace(interruptedException));
            return false;
        }
    }

    @Override
    public void unLock() {
        CusLockInfo cusLockInfo = getLockInfoThreadLocal();
        this.unLock(cusLockInfo);
    }

    @Override
    public void unLock(CusLockInfo cusLockInfo) {
        RLock writeLock = redissonClient.getReadWriteLock(cusLockInfo.getLockKey()).writeLock();
        if (writeLock.isHeldByCurrentThread()) {
            writeLock.unlock();
        }
    }

    @Override
    public String lockType() {
        return LockType.WRITE.getLockType();
    }
}
